using System.Xml.Linq;
using TestCases.Assertions;
using TestCases.Utils;

namespace TestCases.XmlAssert
{
    public enum QualifyForm
    {
        Qualified,
        Unqualified
    }

    public class XAssert
    {
        private readonly ElementAssert _elementAssert;

        private XAssert(IAssertion assertion, XContainer rootContainer)
        {
            _elementAssert = new ElementAssert(assertion, rootContainer);
        }

        public IEAssert That
        {
            get { return _elementAssert; }
        }

        public string Namespace
        {
            get { return _elementAssert.Namespace; }
            set { _elementAssert.Namespace = value; }
        }

        public QualifyForm DefaultElementForm
        {
            get { return _elementAssert.QualifyForm; }
            set { _elementAssert.QualifyForm = value; }
        }

        public QualifyForm DefaultAttributeForm
        {
            get { return _elementAssert.AttributeForm; }
            set { _elementAssert.AttributeForm = value; }
        }

        public XContainer Container
        {
            get { return _elementAssert.Container; }
        }

        public T Deserialize<T>()
        {
            return XmlSerializationUtils.Deserialize<T>(_elementAssert.Container.ToString());
        }

        public static XAssert Using(XDocument document)
        {
            return new XAssert(AssertionUtils.CreateAssert(), document);
        }

        public static XAssert Using(XDocument document, string @namespace)
        {
            return Using(document, @namespace, AssertionUtils.CreateAssert());
        }

        public static XAssert Using(XDocument document, string @namespace, IAssertion assertion)
        {
            return new XAssert(assertion, document)
            {
                Namespace = @namespace
            };
        }

        public static XAssert Using(string xml)
        {
            return new XAssert(AssertionUtils.CreateAssert(), XDocument.Parse(xml));
        }

        public static XAssert Using(string xml, string @namespace)
        {
            return Using(xml, @namespace, AssertionUtils.CreateAssert());
        }

        public static XAssert Using(string xml, string @namespace, IAssertion assertion)
        {
            return new XAssert(assertion, XDocument.Parse(xml))
            {
                Namespace = @namespace
            };
        }

        public static XAssert Using<T>(T obj)
        {
            return Using(XmlSerializationUtils.Serialize(obj),
                XmlSerializationUtils.GetNamespace(typeof(T)),
                AssertionUtils.CreateAssert());
        }

        public static XAssert Using<T>(T obj, string @namespace)
        {
            return Using(obj, @namespace, AssertionUtils.CreateAssert());
        }

        public static XAssert Using<T>(T obj, string @namespace, IAssertion assertion)
        {
            return new XAssert(assertion, XDocument.Parse(XmlSerializationUtils.Serialize(obj)))
            {
                Namespace = @namespace
            };
        }
    }
}